package kbl.language;

enum CommonType {
	LeftHandSide, RightHandSide, Literal, CharacterClass, Asterisk, Plus, Alternate, QuestionMark, Concatenate, LParenthesis, RParenthesis, LBracket, RBracket, Escape;

	boolean isUnaryOrLiteral() {
		return isUnary() || isLiteral();
	}

	boolean isLParenthesisOrLiteral() {
		return isLParenthsis() || isLiteral();
	}

	boolean isParenthsis() {
		switch (this) {
		case LParenthesis:
		case RParenthesis:
			return true;
		default:
			return false;
		}
	}

	boolean isLParenthsis() {
		switch (this) {
		case LParenthesis:
			return true;
		default:
			return false;
		}
	}

	boolean isTarget2Queue(CommonType t) {
		return this.isOperator()
				&& (isRightAssociativePrecedenceLess(t) || isLeftAssociativePrecedenceLessEqual(t));
	}

	private boolean isRightAssociativePrecedenceLess(CommonType t) {
		return (!t.isLeftAssociative() && (t.getPrecedence() < this
				.getPrecedence()));
	}

	private boolean isLeftAssociativePrecedenceLessEqual(CommonType t) {
		return (t.isLeftAssociative() && (t.getPrecedence() <= this
				.getPrecedence()));
	}

	private boolean isOperator() {
		switch (this) {
		case Asterisk:
		case Plus:
		case Alternate:
		case QuestionMark:
		case Concatenate:
			return true;
		default:
			return false;
		}
	}

	private boolean isLiteral() {
		switch (this) {
		case Literal:
		case CharacterClass:
		case LBracket:
		case Escape:
			return true;
		default:
			return false;
		}
	}

	private boolean isLeftAssociative() {
		switch (this) {
		case Asterisk:
		case Plus:
		case QuestionMark:
		case Alternate:
		case Concatenate:
			// left to right
			return true;
		default:
			// right to left '!'
			return false;
		}
	}

	private boolean isUnary() {
		switch (this) {
		case Asterisk:
		case Plus:
		case QuestionMark:
		case RParenthesis:
			// Unary
			return true;
			// Binary '|'
		default:
			return false;
		}
	}

	private int getPrecedence() {
		switch (this) {
		case LParenthesis:
		case RParenthesis:
			return Integer.MAX_VALUE;
		case Asterisk:
		case Plus:
		case QuestionMark:
			return 3; // repetition
		case Concatenate:
			return 2; // concatenation
		case Alternate:
			return 1; // alternation
		default:
			return Integer.MIN_VALUE;
		}
	}
}